/**
 * JAVACC DEMO 1.0
 */
package com.apache.log.service.plugins;

import com.apache.api.manager.PluginConnector;
import com.apache.api.vo.ParamsVo;
import com.apache.api.vo.ResultEntity;
import com.apache.audit.entity.LogModel;
import com.apache.audit.entity.LogModelDetail;
import com.apache.audit.entity.LogOperation;
import com.apache.audit.entity.LogOperationDetail;
import com.apache.cache.util.Validator;
import com.apache.client.UctCoreClient;
import com.apache.log.common.LoadClassUtil;
import com.apache.log.common.PropertiesConfig;
import com.apache.log.manager.UnityBaseManager;
import com.apache.tools.StrUtil;
import com.apache.uct.common.entity.User;
import org.apache.commons.collections.map.CaseInsensitiveMap;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;

/**
 * description:  添加操作日志插件
 *
 */
@Service("logOperationSavePlugin")
public class LogOperationSavePluginImpl implements PluginConnector {

	private Logger log = LoggerFactory.getLogger("logs");

	@Autowired
	private UnityBaseManager unityBaseManager;

	/**
	 * TODO 添加操作日志插件<br>
	 * 参数说明：<br>
	 * log_userEname:操作用户账号；<br>
	 * logType:日志类型<br>
	 * logOperationType：日志操作类型（限登录或退出用login/logout）<br>
	 * log_returnValue:执行结果<br>
	 * logIp：操作IP地址<br>
	 * logClassName：操作模型名<br>
	 * 模型属性与值
	 */
	@SuppressWarnings({ "rawtypes", "unchecked" })
	public Object execute(ParamsVo vo) throws Exception {
		ResultEntity result = new ResultEntity();
		try {
			String logClassName = String.valueOf(vo.getParams("logClassName"));
			LogModel model = getLogModel(logClassName.trim());
			if (Validator.isEmpty(model)) {
				result.setResult("false");
				result.setMessage("没有找到匹配的数据模型，暂时不添加日志信息！");
				log.warn("没有找到匹配的数据模型，暂时不添加日志信息！");
				return result;
			}
			PropertiesConfig.submit(new SaveLogsRun(vo.getParams(),model));//放入队列
			result.setResult("true");
			result.setMessage("数据接收成功");
		} catch (Exception e) {
			result.setResult("false");
			log.error("添加日志信息失败 ", e);
			result.setMessage("添加日志信息失败 ！");
		}
		return result;
	}

	private class SaveLogsRun implements Runnable{
		private LogModel model;
		private Map<String,Object> params;
		public SaveLogsRun(Map<String,Object> params,LogModel model) {
			this.params = params;
			this.model = model;
		}

		@Override
		public void run() {
			String logOperationType = String.valueOf(params.get("logOperationType"));//日志操作类型
			try {
				LogOperation operation = new LogOperation();
				String userEname = String.valueOf(params.get("log_userEname"));
				operation.setModelId(model.getModelId());
				operation.setCreateUser(userEname);
				operation.setCreatedTime(System.currentTimeMillis());
				operation.setLogIp(String.valueOf(params.get("logIp")));
				operation = getUserByEname(operation);
				if (Validator.isNull(logOperationType)) {
					String logType = String.valueOf(params.get("logType"));
					if ("save".equals(logType)) {
						operation.setLogType("添加");
					} else if ("edit".equals(logType)) {
						operation.setLogType("更新");
					} else if ("del".equals(logType)) {
						operation.setLogType("删除");
					}
					if ("del".equals(logType)) {
						loginInfo(operation, String.valueOf(params.get("infoId")));
					} else {
						CaseInsensitiveMap cMap = new CaseInsensitiveMap();
						cMap.putAll(params);
						logSave(operation, cMap);
					}
				} else if ("login".equalsIgnoreCase(logOperationType) || "logout".equalsIgnoreCase(logOperationType)) {//登录日志
					operation.setLogType("登录");
					if ("logout".equalsIgnoreCase(logOperationType))
						operation.setLogType("退出");
					loginInfo(operation,"");
				} else {//业务日志操作
					CaseInsensitiveMap cMap = new CaseInsensitiveMap();
					cMap.putAll(params);
					operation.setLogType("其他");
					logSave(operation, cMap);
				}
			} catch (Exception e){

			}
		}

		/**
		 * description:   记录登录/ 退出日志
		 */
		@SuppressWarnings({ "rawtypes", "unchecked" })
		private void loginInfo(LogOperation operation,String infoId) {
			ParamsVo vo = new ParamsVo();
			vo.setObj(operation);
			List<LogOperationDetail> details = new ArrayList();
			LogOperationDetail detail = new LogOperationDetail();
			detail.setDetailId(Validator.generate());
			if(StrUtil.isNull(infoId)) {//登录退出日志
				detail.setPropertyEname("userEname");
				detail.setPropertyName("用户账号");
				detail.setPropertyValue(operation.getCreateUser());
			} else {//记录删除信息日志
				detail.setPropertyEname("infoId");
				detail.setPropertyName("主键");
				detail.setPropertyValue(infoId);
			}
			details.add(detail);
			vo.setObjs(details);
			vo.setParams("LogModel",model);
			unityBaseManager.saveInfo(vo);
		}

		/**
		 * description:  组织日志对象信息
		 */
		private LogOperation getUserByEname(LogOperation operation) {
			if (Validator.isNull(operation.getCreateUser()))
				return operation;
			try {
				ResultEntity result = UctCoreClient.getUserByProperty("userEname", operation.getCreateUser());
				if ("true".equals(result.getResult()) && !Validator.isEmpty(result.getEntity())) {
					User user = (User) result.getEntity();
					operation.setOrgId(user.getOrgId());
					operation.setOrgEname(user.getOrgEname());
				}
			} catch (Exception e) {
				log.error("获取用户所在机构信息出错", e);
			}
			return operation;
		}

		private void logSave(LogOperation operation, Map beanInfo) {
			ParamsVo vo = new ParamsVo();
			String primaryKey = "";
			List<LogOperationDetail> ods = new ArrayList<LogOperationDetail>();
			if (!beanInfo.isEmpty()) {
				LogModelDetail detail = new LogModelDetail();
				detail.setModelId(operation.getModelId());
				vo.setObj(detail);
				List<LogModelDetail> list = unityBaseManager.getList(vo);
				if (!Validator.isEmpty(list)) {
					for (LogModelDetail ld : list) {
						String key = ld.getColumnEname().toLowerCase();
						String value = String.valueOf(beanInfo.get(key));
						if (Validator.isNotNull(value)) {
							LogOperationDetail od = new LogOperationDetail();
							od.setDetailId(Validator.generate());
							od.setPropertyEname(ld.getColumnEname());
							od.setPropertyName(ld.getColumnCname());
							od.setPropertyValue(value);
							od.setDetailId(Validator.generate());
							od.setPrimaryKey(ld.getPrimaryKey());
							if ("1".equals(ld.getPrimaryKey())) {
								primaryKey = value;
							}
							ods.add(od);
						}
					}
					vo.setObjs(ods);
				}
			}
			operation.setPrimaryKey(primaryKey);
			vo.setObj(operation);
			vo.setParams("LogModel",model);
			unityBaseManager.saveInfo(vo);
		}
	}

	/**
	 * description:  按类名获取模型
	 *
	 * @param className
	 * @return
	 */
	public LogModel getLogModel(String className) {
		if (Validator.isNull(className))
			return null;
		LogModel model = new LogModel();
		model.setModelEname(className);
		ParamsVo<LogModel> vo = new ParamsVo<LogModel>();
		vo.setObj(model);
		List<Map> list = unityBaseManager.getList(vo);
		if (!Validator.isEmpty(list)) {
			Map map = list.get(0);
			return (LogModel) LoadClassUtil.getInstance().convert2Bean(map,model,"");
		}
		return null;
	}

}
